package com.kurt.controller;

import com.kurt.annotation.Log;
import com.kurt.common.PageResult;
import com.kurt.common.Result;
import com.kurt.dto.MenuDTO;
import com.kurt.dto.create.MenuCreateRequest;
import com.kurt.dto.query.MenuQueryRequest;
import com.kurt.dto.update.MenuUpdateRequest;
import com.kurt.service.MenuService;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 菜单管理控制器
 * 提供菜单相关的REST API接口
 */
@Slf4j
@RestController
@RequestMapping("/menus")
@RequiredArgsConstructor
public class MenuController extends BaseController {

    private final MenuService menuService;

    /**
     * 创建菜单
     *
     * @param createRequest 创建请求
     * @return 创建结果
     */
    @Log(title = "创建菜单", businessType = 1)
    @PostMapping
    public Result<MenuDTO> createMenu(@Valid @RequestBody MenuCreateRequest createRequest) {
        try {
            log.info("创建菜单请求: {}", createRequest.getName());
            MenuDTO menu = menuService.createMenu(createRequest);
            return Result.success("菜单创建成功", menu);
        } catch (Exception e) {
            log.error("创建菜单失败", e);
            return Result.error("创建菜单失败: " + e.getMessage());
        }
    }

    /**
     * 更新菜单
     *
     * @param updateRequest 更新请求
     * @return 更新结果
     */
    @Log(title = "更新菜单", businessType = 2)
    @PutMapping
    public Result<MenuDTO> updateMenu(@Valid @RequestBody MenuUpdateRequest updateRequest) {
        try {
            log.info("更新菜单请求: {}", updateRequest.getId());
            MenuDTO menu = menuService.updateMenu(updateRequest);
            return Result.success("菜单更新成功", menu);
        } catch (Exception e) {
            log.error("更新菜单失败", e);
            return Result.error("更新菜单失败: " + e.getMessage());
        }
    }

    /**
     * 根据ID获取菜单详情
     *
     * @param id 菜单ID
     * @return 菜单详情
     */
    @GetMapping("/{id}")
    public Result<MenuDTO> getMenuById(@PathVariable("id") Long id) {
        try {
            log.info("获取菜单详情请求: {}", id);
            MenuDTO menu = menuService.getMenuById(id);
            return Result.success("获取菜单详情成功", menu);
        } catch (Exception e) {
            log.error("获取菜单详情失败", e);
            return Result.error("获取菜单详情失败: " + e.getMessage());
        }
    }

    /**
     * 分页查询菜单
     *
     * @param queryRequest 查询请求
     * @return 分页结果
     */
    @PostMapping("/page")
    public Result<PageResult<MenuDTO>> getMenuPage(@RequestBody MenuQueryRequest queryRequest) {
        try {
            log.info("分页查询菜单请求: {}", queryRequest);
            Page<MenuDTO> page = menuService.getMenuPage(queryRequest);
            PageResult<MenuDTO> pageResult = PageResult.of(
                    page.getNumber() + 1,
                    page.getSize(),
                    page.getTotalElements(),
                    page.getContent()
            );
            return Result.success("分页查询菜单成功", pageResult);
        } catch (Exception e) {
            log.error("分页查询菜单失败", e);
            return Result.error("分页查询菜单失败: " + e.getMessage());
        }
    }

    /**
     * 查询菜单列表
     *
     * @param queryRequest 查询请求
     * @return 菜单列表
     */
    @PostMapping("/list")
    public Result<List<MenuDTO>> getMenuList(@RequestBody MenuQueryRequest queryRequest) {
        try {
            log.info("查询菜单列表请求: {}", queryRequest);
            List<MenuDTO> menus = menuService.getMenuList(queryRequest);
            return Result.success("查询菜单列表成功", menus);
        } catch (Exception e) {
            log.error("查询菜单列表失败", e);
            return Result.error("查询菜单列表失败: " + e.getMessage());
        }
    }

    /**
     * 删除菜单
     *
     * @param id 菜单ID
     * @return 删除结果
     */
    @Log(title = "删除菜单", businessType = 3)
    @DeleteMapping("/{id}")
    public Result<Boolean> deleteMenu(@PathVariable("id") Long id) {
        try {
            log.info("删除菜单请求: {}", id);
            boolean success = menuService.deleteMenu(id);
            return Result.success("菜单删除成功", success);
        } catch (Exception e) {
            log.error("删除菜单失败", e);
            return Result.error("删除菜单失败: " + e.getMessage());
        }
    }

    /**
     * 批量删除菜单
     *
     * @param ids 菜单ID列表
     * @return 删除结果
     */
    @Log(title = "批量删除菜单", businessType = 3)
    @DeleteMapping("/batch")
    public Result<Boolean> deleteMenus(@RequestBody List<Long> ids) {
        try {
            log.info("批量删除菜单请求: {}", ids);
            boolean success = menuService.deleteMenus(ids);
            return Result.success("批量删除菜单成功", success);
        } catch (Exception e) {
            log.error("批量删除菜单失败", e);
            return Result.error("批量删除菜单失败: " + e.getMessage());
        }
    }

    /**
     * 获取菜单树
     *
     * @param parentId 父菜单ID
     * @return 菜单树
     */
    @GetMapping("/tree")
    public Result<List<MenuDTO>> getMenuTree(@RequestParam(required = false) Long parentId) {
        try {
            log.info("获取菜单树请求: parentId={}", parentId);
            List<MenuDTO> tree = menuService.getMenuTree(parentId);
            return Result.success("获取菜单树成功", tree);
        } catch (Exception e) {
            log.error("获取菜单树失败", e);
            return Result.error("获取菜单树失败: " + e.getMessage());
        }
    }

    /**
     * 获取所有菜单树
     *
     * @return 菜单树
     */
    @GetMapping("/tree/all")
    public Result<List<MenuDTO>> getAllMenuTree() {
        try {
            log.info("获取所有菜单树请求");
            List<MenuDTO> tree = menuService.getAllMenuTree();
            return Result.success("获取所有菜单树成功", tree);
        } catch (Exception e) {
            log.error("获取所有菜单树失败", e);
            return Result.error("获取所有菜单树失败: " + e.getMessage());
        }
    }

    /**
     * 根据父菜单ID获取子菜单列表
     *
     * @param parentId 父菜单ID
     * @return 子菜单列表
     */
    @GetMapping("/children/{parentId}")
    public Result<List<MenuDTO>> getChildrenByParentId(@PathVariable("parentId") Long parentId) {
        try {
            log.info("获取子菜单列表请求: parentId={}", parentId);
            List<MenuDTO> children = menuService.getChildrenByParentId(parentId);
            return Result.success("获取子菜单列表成功", children);
        } catch (Exception e) {
            log.error("获取子菜单列表失败", e);
            return Result.error("获取子菜单列表失败: " + e.getMessage());
        }
    }

    /**
     * 根据用户ID获取用户菜单权限
     *
     * @param userId 用户ID
     * @return 菜单列表
     */
    @GetMapping("/user/{userId}")
    public Result<List<MenuDTO>> getMenusByUserId(@PathVariable("userId") Long userId) {
        try {
            log.info("获取用户菜单权限请求: userId={}", userId);
            List<MenuDTO> menus = menuService.getMenusByUserId(userId);
            return Result.success("获取用户菜单权限成功", menus);
        } catch (Exception e) {
            log.error("获取用户菜单权限失败", e);
            return Result.error("获取用户菜单权限失败: " + e.getMessage());
        }
    }

    /**
     * 根据角色ID获取角色菜单权限
     *
     * @param roleId 角色ID
     * @return 菜单列表
     */
    @GetMapping("/role/{roleId}")
    public Result<List<MenuDTO>> getMenusByRoleId(@PathVariable("roleId") Long roleId) {
        try {
            log.info("获取角色菜单权限请求: roleId={}", roleId);
            List<MenuDTO> menus = menuService.getMenusByRoleId(roleId);
            return Result.success("获取角色菜单权限成功", menus);
        } catch (Exception e) {
            log.error("获取角色菜单权限失败", e);
            return Result.error("获取角色菜单权限失败: " + e.getMessage());
        }
    }

    /**
     * 检查菜单名称是否存在
     *
     * @param name 菜单名称
     * @return 是否存在
     */
    @GetMapping("/exists/name/{name}")
    public Result<Boolean> existsByName(@PathVariable("name") String name) {
        try {
            log.info("检查菜单名称是否存在请求: {}", name);
            boolean exists = menuService.existsByName(name);
            return Result.success("检查菜单名称是否存在成功", exists);
        } catch (Exception e) {
            log.error("检查菜单名称是否存在失败", e);
            return Result.error("检查菜单名称是否存在失败: " + e.getMessage());
        }
    }

    /**
     * 检查菜单编码是否存在
     *
     * @param code 菜单编码
     * @return 是否存在
     */
    @GetMapping("/exists/code/{code}")
    public Result<Boolean> existsByCode(@PathVariable("code") String code) {
        try {
            log.info("检查菜单编码是否存在请求: {}", code);
            boolean exists = menuService.existsByCode(code);
            return Result.success("检查菜单编码是否存在成功", exists);
        } catch (Exception e) {
            log.error("检查菜单编码是否存在失败", e);
            return Result.error("检查菜单编码是否存在失败: " + e.getMessage());
        }
    }

    /**
     * 更新菜单状态
     *
     * @param id     菜单ID
     * @param status 状态
     * @return 更新结果
     */
    @Log(title = "更新菜单状态", businessType = 2)
    @PostMapping("/{id}/status")
    public Result<Boolean> updateStatus(@PathVariable("id") Long id, @RequestParam Integer status) {
        try {
            log.info("更新菜单状态请求: id={}, status={}", id, status);
            boolean success = menuService.updateStatus(id, status);
            return Result.success("菜单状态更新成功", success);
        } catch (Exception e) {
            log.error("更新菜单状态失败", e);
            return Result.error("更新菜单状态失败: " + e.getMessage());
        }
    }

    /**
     * 更新菜单排序
     *
     * @param id        菜单ID
     * @param sortOrder 排序号
     * @return 更新结果
     */
    @Log(title = "更新菜单排序", businessType = 2)
    @PostMapping("/{id}/sort")
    public Result<Boolean> updateSortOrder(@PathVariable("id") Long id, @RequestParam Integer sortOrder) {
        try {
            log.info("更新菜单排序请求: id={}, sortOrder={}", id, sortOrder);
            boolean success = menuService.updateSortOrder(id, sortOrder);
            return Result.success("菜单排序更新成功", success);
        } catch (Exception e) {
            log.error("更新菜单排序失败", e);
            return Result.error("更新菜单排序失败: " + e.getMessage());
        }
    }

    /**
     * 移动菜单到新的父菜单下
     *
     * @param id          菜单ID
     * @param newParentId 新父菜单ID
     * @return 移动结果
     */
    @Log(title = "移动菜单到新的父菜单下", businessType = 2)
    @PostMapping("/{id}/move")
    public Result<Boolean> moveMenu(@PathVariable("id") Long id, @RequestParam Long newParentId) {
        try {
            log.info("移动菜单请求: id={}, newParentId={}", id, newParentId);
            boolean success = menuService.moveMenu(id, newParentId);
            return Result.success("菜单移动成功", success);
        } catch (Exception e) {
            log.error("移动菜单失败", e);
            return Result.error("移动菜单失败: " + e.getMessage());
        }
    }
}
